# ******************************************************************************
#  Copyright (c) 2021-2022. Kneron Inc. All rights reserved.                   *
# ******************************************************************************
from ..KPStructure import BufferBase
from typing import Type, Union, Any
import abc
import ctypes
import json
import numpy


class JsonEncodeNumpy(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, numpy.ndarray):
            return str(obj).split(sep='\n')
        elif isinstance(obj, numpy.integer):
            return int(obj)
        elif isinstance(obj, numpy.floating):
            return float(obj)
        return super(JsonEncodeNumpy, self).default(obj)


class ValueRepresentBase(metaclass=abc.ABCMeta):
    def __str__(self):
        return json.dumps(self.get_member_variable_dict(), indent=4, sort_keys=False, cls=JsonEncodeNumpy)

    def __repr__(self):
        return json.dumps(self.get_member_variable_dict(), indent=4, sort_keys=False, cls=JsonEncodeNumpy)

    @abc.abstractmethod
    def get_member_variable_dict(self) -> dict:
        """
        Represent member variables with Dict format.

        Returns
        -------
        ret : dict
            Represent member variables in Dict format.
        """
        pass


class ValueBase(metaclass=abc.ABCMeta):
    def __init__(self, element_buffer_class: Type[BufferBase], *args: Any, **kw: Any):
        self._is_allocate_from_c = False

        if issubclass(element_buffer_class, BufferBase):
            self._element_buffer = element_buffer_class(*args, **kw)
            self._cast_element_buffer()
        else:
            raise AttributeError(
                '{} is not sub-class of {}'.format(element_buffer_class.__name__, ctypes.Structure.__name__))

    def _get_element_buffer(self) -> Union[None, BufferBase]:
        return self._element_buffer

    @abc.abstractmethod
    def _cast_element_buffer(self) -> None:
        pass
